<?php defined('BASEPATH') OR exit('No direct script access allowed');

/**
 * Admin controller for the users module
 *
 * @author 		Phil Sturgeon - PyroCMS Dev Team
 * @package 	PyroCMS
 * @subpackage 	Users module
 * @category	Modules
 */
class Users extends Admin_Controller {

	/**
	 * Validation array
	 * @access private
	 * @var array
	 */
	private $validation_rules = array(
		array(
			'field' => 'first_name',
			'label' => 'lang:user_first_name_label',
			'rules' => 'required|utf8'
		),
		array(
			'field' => 'last_name',
			'label' => 'lang:user_last_name_label',
			'rules' => 'utf8'
		),
		array(
			'field' => 'email',
			'label' => 'lang:user_email_label',
			'rules' => 'required|valid_email'
		),
		array(
			'field' => 'password',
			'label' => 'lang:user_password_label',
			'rules' => 'min_length[6]|max_length[20]'
		),
		array(
			'field' => 'username',
			'label' => 'lang:user_username',
			'rules' => 'required|min_length[3]|max_length[20]'
//			'rules' => 'required|alpha_dot_dash|min_length[3]|max_length[20]'
		),
		array(
			'field' => 'display_name',
			'label' => 'lang:user_display_name',
			'rules' => 'min_length[3]|max_length[50]'
		),
		array(
			'field' => 'group_id',
			'label' => 'lang:user_group_label',
			'rules' => 'required|callback__group_check'
		),
		array(
			'field' => 'active',
			'label' => 'lang:user_active_label',
			'rules' => ''
		)
	);

	/**
	 * Constructor method
	 * @access public
	 * @return void
	 */
	public function __construct()
	{
		parent::__construct();

		// Load the required classes
		$this->load->model('users/user_model', 'user_m');
		$this->load->model('groups/group_model', 'group_m');
		$this->load->helper('user');
		$this->load->library('form_validation');
		$this->lang->load('users/user');
		$this->lang->load('users/group');
		$this->lang->load('users/permission');
		$this->data['groups'] = $this->group_m->get_all();
		$this->data['groups_select'] = array_for_select($this->data['groups'], 'id', 'description');
		
		array_unshift($this->shortcuts, array('name' => lang('menu_users'), 'link' => site_url('admin/users')),
				array('name' => lang('menu_2_users_create'), 'link' => site_url('admin/users/create')),
				array('name' => lang('menu_2_create_group'), 'link' => site_url('admin/users/create_group')),
				array('name' => lang('menu_2_groups'), 'link' => site_url('admin/users/groups'))
		);
		
		$this->template->set_data(array(
				'shortcuts' => $this->shortcuts,
				'groups_select' => $this->data['groups_select'],
				'groups' => $this->data['groups']));
	}

	/**
	 * List all users
	 * @access public
	 * @return void
	 */
	public function index()
	{
		$pagination = create_pagination('admin/users/index' , $this->users_m->count_all(), 15, 4);
		$users = $this->users_m->limit($pagination['limit'])->get_all();
		$this->template->load('users/list', array(
			'pagination' => $pagination,
			'users' => $users
		));
	}
	public function groups()
	{
		$this->template->load('groups/list', array(
			'groups' => $this->data['groups']
		));
	}
	public function create_group()
	{
		$validation_rules = array(
				array(
						'field' => 'name',
						'label' => lang('groups.name'),
						'rules' => 'trim|required|max_length[100]'
				),
				array(
						'field' => 'description',
						'label' => lang('groups.description'),
						'rules' => 'trim|required|max_length[250]'
				)
		);
		if ($_POST)
		{
			$this->_reset_validation();
			$this->form_validation->set_rules($validation_rules);

			if ($this->form_validation->run())
			{
				$this->group_m->insert($this->input->post())
					? $this->session->set_flashdata('success', sprintf(lang('groups.add_success'), $this->input->post('name')))
					: $this->session->set_flashdata('error', sprintf(lang('groups.add_error'), $this->input->post('name')));

				redirect('admin/users/groups');
			}
		}

		// Loop through each validation rule
		foreach ($validation_rules as $rule)
		{
			$group->{$rule['field']} = set_value($rule['field']);
		}
		$this->template->set('site_title', lang('groups.add_title'))->load('groups/create', array('group' => $group));
	}
	
	public function edit_group($id)
	{
		$validation_rules = array(
				array(
						'field' => 'name',
						'label' => lang('groups.name'),
						'rules' => 'trim|required|max_length[100]'
				),
				array(
						'field' => 'description',
						'label' => lang('groups.description'),
						'rules' => 'trim|required|max_length[250]'
				)
		);
		$group = $this->group_m->get($id);

		// Make sure we found something
		$group or redirect('admin/groups');

		if ($_POST)
		{
			// Got validation?
			if ($group->name == 'admin' OR $group->name == 'user')
			{
				//if they're changing description on admin or user save the old name
				$_POST['name'] = $group->name;
				$this->_reset_validation();
				$this->form_validation->set_rules('description', lang('groups.description'), 'trim|required|max_length[250]');
			}
			else
			{
				$this->_reset_validation();
				$this->form_validation->set_rules($validation_rules);
			}
			
			if ($this->form_validation->run())
			{
				$this->group_m->update($id, $this->input->post())
					? $this->session->set_flashdata('success', sprintf(lang('groups.edit_success'), $this->input->post('name')))
					: $this->session->set_flashdata('error', sprintf(lang('groups.edit_error'), $this->input->post('name')));

				// Redirect
				redirect('admin/users/groups');
			}
		}
		$this->template->set('site_title', lang('groups.edit_title'))->load('groups/edit', array('group' => $group));
	}
	
	/**
	 * Delete group role(s)
	 *
	 * @access public
	 * @param int $id The ID of the group to delete
	 * @return void
	 */
	public function delete_group($id = 0)
	{
		$this->group_m->delete($id)
		? $this->session->set_flashdata('success', lang('groups.delete_success'))
		: $this->session->set_flashdata('error', lang('groups.delete_error'));
	
		redirect('admin/users/groups');
	}
	
	public function permissions_group($group_id)
	{
		if ($_POST)
		{
			// register the user
			$this->permission_m->save($group_id, $this->input->post('modules'), $this->input->post('module_roles'));
	
			$this->session->set_flashdata('success', lang('permissions.message_group_saved'));
	
			redirect('admin/users/permissions_group/'.$group_id);
		}
		
		$this->lang->load('files/permission');
		$this->lang->load('regions/permission');
		$this->lang->load('channels/permission');
		$this->lang->load('agencies/permission');
		$this->lang->load('pickuppoints/permission');
		$this->lang->load('hotels/permission');
		$this->lang->load('tours/permission');
		$this->lang->load('articles/permission');
		$this->lang->load('attractions/permission');
		$this->lang->load('tags/permission');
		$this->lang->load('categories/permission');
		$group = $this->group_m->get($group_id);
		$edit_permissions = $this->permission_m->get_group($group_id);
		$permisison_modules = $this->config->item('modules');
	
		$this->template->load('groups/permissions', array(
				'edit_permissions' => $edit_permissions,
				'permisison_modules' => $permisison_modules,
				'group' => $group
		));
	}
	
	public function search()
	{
		$active = $this->input->post('active');
		$group = $this->input->post('group');
		$keyword = $this->input->post('keyword');
		
		$url_active = substr($this->uri->segment(4, 'active_'), 7);
		$url_group = substr($this->uri->segment(5, 'group_'), 6);
		$url_keyword = url_base64_decode(substr($this->uri->segment(6, 'keyword_'), 8));
		
		$keyword = $keyword === FALSE? $url_keyword: $keyword;
		$active = $active === FALSE? $url_active: $active;
		$group = $group === FALSE? $url_group: $group;
		
		$pagination = create_pagination(
				'admin/users/search/active_' . $active. '/group_'. $group . '/keyword_'. url_base64_encode($keyword) , $this->users_m->count_search($keyword , $group, $active), 15, 7);
		$users = $this->users_m->search($keyword , $group, $active, $pagination['limit']);
		
		$this->template->load('users/search', array(
			'users' => $users,		
			'keyword' => $keyword,		
			'group' => $group,		
			'pagination' => $pagination,
			'active' => $active	
		));
	}

	/**
	 * Method for handling different form actions
	 * @access public
	 * @return void
	 */
	public function action()
	{
		// Determine the type of action
		switch ($this->input->post('btnAction'))
		{
			case 'activate':
				$this->activate();
				break;
			case 'deactivate':
				$this->deactivate();
				break;
			case 'delete':
				$this->delete();
				break;
			default:
				redirect('admin/users');
				break;
		}
	}

	/**
	 * Create a new user
	 *
	 * @access public
	 * @return void
	 */
	public function create()
	{
		// We need a password don't you think?
		$this->validation_rules[2]['rules'] .= '|callback__email_check';
		$this->validation_rules[3]['rules'] .= '|required';
		$this->validation_rules[5]['rules'] .= '|callback__username_check';

		// Set the validation rules
		$this->form_validation->set_rules($this->validation_rules);

		$email = $this->input->post('email');
		$password = $this->input->post('password');
		$username = $this->input->post('username');

		$user_data = array(
			'first_name' => $this->input->post('first_name'),
			'last_name' => $this->input->post('last_name'),
			'display_name' => $this->input->post('display_name'),
			'group_id' => $this->input->post('group_id')
		);

		if ($this->form_validation->run() !== FALSE)
		{
			// Hack to activate immediately
			if ($this->input->post('active'))
			{
				$this->config->config['ion_auth']['email_activation'] = FALSE;
			}

			$group = $this->group_m->get($this->input->post('group_id'));

			// Try to register the user
			if ($user_id = $this->ion_auth->register($username, $password, $email, $user_data, $group->name))
			{
				// Set the flashdata message and redirect
				$this->session->set_flashdata('success', $this->ion_auth->messages());
				redirect('admin/users');
			}
			// Error
			else
			{
				$this->data['error_string'] = $this->ion_auth->errors();
			}
		}
		else
		{
			// Dirty hack that fixes the issue of having to re-add all data upon an error
			if ($_POST)
			{
				$member = (object) $_POST;
			}
		}
		// Loop through each validation rule
		foreach ($this->validation_rules as $rule)
		{
			$member->{$rule['field']} = set_value($rule['field']);
		}

		// Render the view
		$this->data['member'] = & $member;
		$this->data['site_title'] = lang('user_add_title');
		$this->template->load('users/create', $this->data);
	}

	/**
	 * Edit an existing user
	 *
	 * @access public
	 * @param int $id The ID of the user to edit
	 * @return void
	 */
	public function edit($id = 0)
	{
		// Get the user's data
		$member = $this->ion_auth->get_user($id);

		// Got user?
		if (!$member)
		{
			$this->session->set_flashdata('error', $this->lang->line('user_edit_user_not_found_error'));
			redirect('admin/users');
		}

		// Check to see if we are changing usernames
		if ($member->username != $this->input->post('username'))
		{
			$this->validation_rules[6]['rules'] .= '|callback__username_check';
		}

		// Check to see if we are changing emails
		if ($member->email != $this->input->post('email'))
		{
			$this->validation_rules[5]['rules'] .= '|callback__email_check';
		}

		// Run the validation
		$this->form_validation->set_rules($this->validation_rules);
		if ($this->form_validation->run() === TRUE)
		{
			// Get the POST data
			$update_data['first_name'] = $this->input->post('first_name');
			$update_data['last_name'] = $this->input->post('last_name');
			$update_data['email'] = $this->input->post('email');
			$update_data['active'] = $this->input->post('active');
			$update_data['username'] = $this->input->post('username');
			$update_data['display_name'] = $this->input->post('display_name');
			$update_data['group_id'] = $this->input->post('group_id');

			// Password provided, hash it for storage
			if ($this->input->post('password'))
			{
				$update_data['password'] = $this->input->post('password');
			}

			if ($this->ion_auth->update_user($id, $update_data))
			{
				$this->session->set_flashdata('success', $this->ion_auth->messages());
			}
			else
			{
				$this->session->set_flashdata('error', $this->ion_auth->errors());
			}

			// Redirect the user
			redirect('admin/users');
		}
		else
		{
			// Dirty hack that fixes the issue of having to re-add all data upon an error
			if ($_POST)
			{
				$member = (object) $_POST;
				$member->full_name = $member->first_name . ' ' . $member->last_name;
			}
		}
		// Loop through each validation rule
		foreach ($this->validation_rules as $rule)
		{
			if ($this->input->post($rule['field']) !== FALSE)
			{
				$member->{$rule['field']} = set_value($rule['field']);
			}
		}

		$this->template->load('users/edit', array(
			'member' => $member,	
			'site_title' => sprintf(lang('user_edit_title'), $member->full_name),	
		));
	}

	/**
	 * Show a user preview
	 * @access	public
	 * @param	int $id The ID of the user
	 * @return	void
	 */
	public function preview($id = 0)
	{
		$member = $this->ion_auth->get_user($id);
		$this->template->load('users/preview', array('member' => $member));
	}

	/**
	 * Activate a user
	 * @access public
	 * @param int $id The ID of the user to activate
	 * @return void
	 */
	public function activate()
	{
		// Activate multiple
		if ( ! ($ids = $this->input->post('action_to')))
		{
			$this->session->set_flashdata('error', $this->lang->line('user_activate_error'));
			redirect('admin/users');
		}

		$activated = 0;
		$to_activate = 0;
		foreach ($ids as $id)
		{
			if ($this->ion_auth->activate($id))
			{
				$activated++;
			}
			$to_activate++;
		}
		$this->session->set_flashdata('success', sprintf($this->lang->line('user_activate_success'), $activated, $to_activate));

		redirect('admin/users');
	}
	public function deactivate()
	{
		// Activate multiple
		if ( ! ($ids = $this->input->post('action_to')))
		{
			$this->session->set_flashdata('error', $this->lang->line('user_activate_error'));
			redirect('admin/users');
		}

		$activated = 0;
		$to_activate = 0;
		foreach ($ids as $id)
		{
			if ($this->ion_auth->deactivate($id))
			{
				$activated++;
			}
			$to_activate++;
		}
		$this->session->set_flashdata('success', sprintf($this->lang->line('user_deactivate_success'), $activated, $to_activate));

		redirect('admin/users');
	}

	/**
	 * Delete an existing user
	 *
	 * @access public
	 * @param int $id The ID of the user to delete
	 * @return void
	 */
	public function delete($id = 0)
	{
		$ids = ($id > 0) ? array($id) : $this->input->post('action_to');

		if (!empty($ids))
		{
			$deleted = 0;
			$to_delete = 0;
			foreach ($ids as $id)
			{
				// Make sure the admin is not trying to delete themself
				if ($this->ion_auth->get_user()->id == $id)
				{
					$this->session->set_flashdata('notice', $this->lang->line('user_delete_self_error'));
					continue;
				}

				if ($this->ion_auth->delete_user($id))
				{
					$deleted++;
				}
				$to_delete++;
			}

			if ($to_delete > 0)
			{
				$this->session->set_flashdata('success', sprintf($this->lang->line('user_mass_delete_success'), $deleted, $to_delete));
			}
		}
		// The array of id's to delete is empty
		else
			$this->session->set_flashdata('error', $this->lang->line('user_mass_delete_error'));

		// Redirect
		redirect('admin/users');
	}

	/**
	 * Username check
	 *
	 * @return bool
	 * @author Ben Edmunds
	 * */
	public function _username_check($username)
	{
		if ($this->ion_auth->username_check($username))
		{
			$this->form_validation->set_message('_username_check', $this->lang->line('user_error_username'));
			return FALSE;
		}
		else
		{
			return TRUE;
		}
	}

	/**
	 * Email check
	 *
	 * @return bool
	 * @author Ben Edmunds
	 * */
	public function _email_check($email)
	{
		if ($this->ion_auth->email_check($email))
		{
			$this->form_validation->set_message('_email_check', $this->lang->line('user_error_email'));
			return FALSE;
		}
		else
		{
			return TRUE;
		}
	}

	/**
	 * Check that a proper group has been selected
	 *
	 * @return bool
	 * @author Stephen Cozart
	 */
	public function _group_check($group)
	{
		if ( ! $this->group_m->get($group))
		{
			$this->form_validation->set_message('_group_check', $this->lang->line('regex_match'));
			return FALSE;
		}
		return TRUE;
	}

}

/* End of file admin.php */